﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BCCommon;
using System.Text;
using System.Net;
using Microsoft.AspNetCore.Mvc;
using BCDto.MakeStaticPagingComponent.WebsiteTemplateAttachment;
using BCTMSRESTful.Configs;
using BCService.Utils;
using BCService.MakeStaticPagingComponent.WebsiteTemplateAttachmentService;
using BCDto.Tools;
using Microsoft.AspNetCore.Http;
using System.IO;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using BCCommon.Enums;
using Newtonsoft.Json;
using Microsoft.Extensions.Configuration;
using BCService.UploadHandleComponent;
using BCCommon.ExceptionExtensions;

namespace BCTMSRESTful.Controllers.Management.MakeStaticPagingComponent
{
    /// <summary>
    /// 网站模板附件
    /// </summary>
    [ApiExplorerSettings(GroupName = "Admin")]
    [Route("api/v1/sim/[controller]")]
    public class WebsiteTemplateAttachmentController : ManagementBaseController
    {
        private readonly IConfiguration configuration;
        private readonly IWebsiteTemplateAttachmentService websiteTemplateAttachmentService;
        private readonly IUploadFileInfoHandleService uploadFileInfoHandleService;

        public WebsiteTemplateAttachmentController(IConfiguration configuration,
            IWebsiteTemplateAttachmentService websiteTemplateAttachmentService, 
            IUploadFileInfoHandleService uploadFileInfoHandleService)
        {
            this.configuration = configuration;
            this.websiteTemplateAttachmentService = websiteTemplateAttachmentService;
            this.uploadFileInfoHandleService = uploadFileInfoHandleService;
        }

        #region 添加网站模板附件
        /// <summary>
        ///  添加网站模板附件
        /// </summary>
        /// <param name="requestDto">网站模板附件信息</param>
        /// <response code="201">添加网站模板附件成功</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        /// <returns></returns>
        [HttpPost]
        [Log("添加网站模板附件")]
        [ProducesResponseType(typeof(WebsiteTemplateAttachmentDto), 201)]
        public IActionResult Post(
            [FromBody]WebsiteTemplateAttachmentRequestDto requestDto)
        {
            var result = this.websiteTemplateAttachmentService.Add(requestDto,this.Admin);
            return StatusCode((int)HttpStatusCode.Created, result);
        }
        #endregion

        #region 修改网站模板附件
        /// <summary>
        ///  修改网站模板附件
        /// </summary>
        /// <param name="websiteTemplateAttachmentId">网站模板附件Id</param>
        /// <param name="requestDto">网站模板附件信息</param>
        /// <response code="200">修改网站模板附件成功</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        /// <returns></returns>
        [HttpPut("{website_template_attachment_id}")]
        [Log("修改网站模板附件")]
        [ProducesResponseType(typeof(WebsiteTemplateAttachmentDto), 200)]
        public IActionResult Put([FromRoute(Name = "website_template_attachment_id")]int websiteTemplateAttachmentId, [FromBody]WebsiteTemplateAttachmentRequestDto requestDto)
        {
            WebsiteTemplateAttachmentPutDto putDto = requestDto.As<WebsiteTemplateAttachmentPutDto>();
            putDto.WebsiteTemplateAttachmentId = websiteTemplateAttachmentId;
            return StatusCode((int)HttpStatusCode.OK, this.websiteTemplateAttachmentService.Update(putDto,this.Admin));
        }
        #endregion

        #region 删除网站模板附件
        /// <summary>
        ///  删除网站模板附件
        /// </summary>
        /// <param name="websiteTemplateAttachmentId">网站模板附件Id</param>
        /// <response code="204">删除网站模板附件成功</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        /// <returns></returns>
        [HttpDelete("{website_template_attachment_id}")]
        [Log("删除网站模板附件")]
        [ProducesResponseType(typeof(NoContentResult), 204)]
        public IActionResult Delete([FromRoute(Name = "website_template_attachment_id")]int websiteTemplateAttachmentId)
        {
            this.websiteTemplateAttachmentService.Delete(websiteTemplateAttachmentId);
            return StatusCode((int)HttpStatusCode.NoContent);
        }
        #endregion

        #region 获取网站模板附件
        /// <summary>
        ///  获取网站模板附件
        /// </summary>
        /// <param name="websiteTemplateAttachmentId">网站模板附件Id</param>
        /// <response code="200">获取网站模板附件</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        /// <returns></returns>
        [HttpGet("{website_template_attachment_id}")]
        [ProducesResponseType(typeof(WebsiteTemplateAttachmentDto), 200)]
        public IActionResult Get([FromRoute(Name = "website_template_attachment_id")]int websiteTemplateAttachmentId)
        {
            return StatusCode((int)HttpStatusCode.OK, this.websiteTemplateAttachmentService.Get(websiteTemplateAttachmentId));
        }
        #endregion

        #region 获取网站模板附件列表
        /// <summary>
        ///  获取网站模板附件列表
        /// </summary>
        /// <param name="websiteTemplateId">网站模板Id</param>
        /// <response code="200">获取网站模板附件列表</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        /// <returns></returns>
        [HttpGet("[action]/{website_template_id}")]
        [ProducesResponseType(typeof(IEnumerable<WebsiteTemplateAttachmentDto>), 200)]
        public IActionResult List([FromRoute(Name = "website_template_id")]int websiteTemplateId)
        {
            return StatusCode((int)HttpStatusCode.OK, this.websiteTemplateAttachmentService.GetList(websiteTemplateId));
        }
        #endregion

        #region 获取网站模板附件（分页）
        /// <summary>
        ///  获取网站模板附件（分页）
        /// </summary>
        /// <param name="websiteTemplateId">网站模板Id</param>
        /// <param name="start">开始时间</param>
        /// <param name="end">结束时间</param>
        /// <param name="sortName">排序字段</param>
        /// <param name="ascending">升序</param>
        /// <param name="index">当前页码</param>
        /// <param name="size">当前页大小</param>
        /// <response code="200">获取网站模板附件（分页）</response>
        /// <response code="400">请求参数或输入的数据不正确。</response>
        /// <response code="500">服务器发生错误。</response>
        /// <response code="501">某些功能尚未实现。</response>
        /// <returns></returns>
        [HttpGet("[action]")]
        [ProducesResponseType(typeof(PageableList<WebsiteTemplateAttachmentDto>), 200)]
        public IActionResult Query(
            [FromQuery(Name = "website_template_id")]int websiteTemplateId,
            [FromQuery(Name = "start")]DateTime? start,
            [FromQuery(Name = "end")]DateTime? end,
            [FromQuery(Name = "sort_name")]string sortName,
            [FromQuery(Name = "ascending")]bool? ascending,
            [FromQuery(Name = "index")]int index = 1,
            [FromQuery(Name = "size")]int size = 10)
        {
            return StatusCode((int)HttpStatusCode.OK, this.websiteTemplateAttachmentService.Query(websiteTemplateId, start, end, sortName, ascending, index, size));
        }
        #endregion

        /// <summary>
        /// 上传CSS及JS文件。
        /// </summary>
        /// <param name="from">上传文件信息</param>
        /// <response code="200">上传CSS及JS文件成功。</response>
        /// <response code="401">请求需要认证或者认证信息已过期。</response>
        /// <response code="403">无权访问指定的功能。</response>
        /// <returns></returns>
        [HttpPost("[action]")]
        [ProducesResponseType(typeof(ImportResultDto), 200)]
        public IActionResult Upload([FromForm]IFormCollection from)
        {
            var data = from.Files["data"];
            string fileName = from["fileName"];
            string usage = from["usage"];
            if (string.IsNullOrWhiteSpace(fileName))
            {
                throw new ArgumentException("文件名称不能为空");
            }

            if (!fileName.Contains("."))
            {
                throw new ArgumentException("文件名称未包含文件后缀名");
            }
            if (string.IsNullOrWhiteSpace(usage))
            {
                throw new ArgumentException("文件用途不能为空");
            }
            //允许上传的类型
            Dictionary<string, string> allowType = new Dictionary<string, string>();
            allowType.Add(".jpg", "image");
            allowType.Add(".jpeg", "image");
            allowType.Add(".gif", "image");
            allowType.Add(".bmp", "image");
            allowType.Add(".png", "image");

            allowType.Add(".doc", "office");
            allowType.Add(".docx", "office");
            allowType.Add(".xls", "office");
            allowType.Add(".xlsx", "office");
            allowType.Add(".csv", "office");
            allowType.Add(".ppt", "office");
            allowType.Add(".pptx", "office");
            allowType.Add(".pub", "office");

            allowType.Add(".mp4", "video");

            allowType.Add(".mp3", "voice");
            allowType.Add(".amr", "voice");
            allowType.Add(".wav", "voice");
            allowType.Add(".wma", "voice");

            allowType.Add(".ttf", "font");
            allowType.Add(".eot", "font");
            allowType.Add(".svg", "font");
            allowType.Add(".woff", "font");

            allowType.Add(".css", "css");
            allowType.Add(".js", "js");
            
            string fileSuffix = Path.GetExtension(fileName).ToLower();                                                               //文件扩展名
            if (!allowType.TryGetValue(fileSuffix,out string fileDirectory))
            {
                throw new ArgumentException("文件格式错误!");
            }
            
            string baseFileName = fileName.ToLower().Replace(fileSuffix, "");
            
            Regex regex = new Regex(RegexPatterns.ENGLISH_AND_NUMBER_AND_POINT);
            if (!regex.IsMatch(baseFileName))
            {
                throw new ArgumentException("文件名不正确，仅支持字母数字下划线及横线组合的文件名!");
            }

            string applicationRootDirectory = Directory.GetParent(Directory.GetCurrentDirectory()).FullName;                         //当前系统根目录
            string websiteRootDirectory = Path.Combine(applicationRootDirectory, configuration["WebsiteName"]);                      //当前网站目录
            
            bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
            if (!isWindows)
            {
                fileDirectory = fileDirectory.Replace("\\", "/");
            }
            string directoryPath = Path.Combine(websiteRootDirectory, fileDirectory);                                               //文件所在目录
            //if (from.Any(p => p.Key.Equals("remark")))
            //{
            //    if (Enum.TryParse(typeof(UploadFileRemarkType), from["remark"], out object value))
            //    {
            //        UploadFileRemarkType remarkType = (UploadFileRemarkType)value;
            //        if (remarkType != UploadFileRemarkType.SelfWebsite)
            //        {
            //            throw new ArgumentException("此接口remark仅支持类型：网站自用!");
            //        }
            //        if (from.Any(p => p.Key.Equals("remarkJSON")))
            //        {
            //            var remarks = JsonConvert.DeserializeObject<Dictionary<string, object>>(from["remarkJSON"]);
            //            if (!remarks.TryGetValue("page_code", out object pageCode))
            //            {
            //                throw new ArgumentException("获取remarkJSON中的page_code（页面标记码）失败!");
            //            }
            //            directoryPath = Path.Combine(directoryPath, pageCode.ToString().ToLower());
            //            fileDirectory = Path.Combine(fileDirectory, pageCode.ToString().ToLower());
            //        }
            //        else
            //        {
            //            throw new ArgumentException("当remark不为空时，remarkJSON必须存在!");
            //        }
            //    }
            //    else
            //    {
            //        throw new ArgumentException("备注服务类型不正确。");
            //    }
            //}
            string path = Path.Combine(directoryPath, fileName);                                                                    //最终目标文件路径
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }

            if (data == null || data.Length <= 0)
            {
                return BadRequest("文件错误！");
            }
            
            using (FileStream fs = new FileStream(path, FileMode.Create))
            {
                data.CopyTo(fs);
                Stream sm = data.OpenReadStream();
                var br = new BinaryReader(sm);
                if (fileDirectory.Contains("image"))
                {
                    CheckFileSecurity(br);
                }
                byte[] bytes = br.ReadBytes((int)sm.Length);
                fs.Flush();
            }

            var host = configuration["DefaultHost"];

            ImportResultDto result = new ImportResultDto();
            result.Src = string.Format("{0}/{1}/{2}", host.TrimEnd('/'), fileDirectory, fileName);
            return Ok(result);
        }

        /// <summary>
        /// 文件安全检查
        /// </summary>
        /// <param name="br">二进制字节流</param>
        private void CheckFileSecurity(BinaryReader br)
        {
            string fileClass;
            byte buffer;
            byte[] b = new byte[2];
            buffer = br.ReadByte();
            b[0] = buffer;
            fileClass = buffer.ToString();
            buffer = br.ReadByte();
            b[1] = buffer;
            fileClass += buffer.ToString();
            Dictionary<string, string> securityCode = new Dictionary<string, string>();
            //7790是Exe,8297是rar
            securityCode.Add("255216", "jpg");
            securityCode.Add("7173", "gif");
            securityCode.Add("6677", "BMP");
            securityCode.Add("13780", "PNG");
            if (!securityCode.Any(p => p.Key.Equals(fileClass)))
            {
                throw new UploadFileException("此文件不允许上传。");
            }
        }

    }
}

